This just does the renaming, and drops the factory.
gailstatusbar.c \
gailtextcell.c \
gailtextutil.c \
- gailtextview.c \
+ gtktextviewaccessible.c \
gailtogglebutton.c \
gailtoplevel.c \
gailtreeview.c \
gailstatusbar.h \
gailtextcell.h \
gailtextutil.h \
- gailtextview.h \
+ gtktextviewaccessible.h \
gailtogglebutton.h \
gailtoplevel.h \
gailtreeview.h \
#include "gailseparator.h"
#include "gailstatusbar.h"
#include "gailtextcell.h"
-#include "gailtextview.h"
#include "gailtogglebutton.h"
#include "gailtoplevel.h"
#include "gailtreeview.h"
GAIL_IMPLEMENT_FACTORY_WITH_FUNC (GAIL_TYPE_MENU_ITEM, GailMenuItem, gail_menu_item, gail_menu_item_new)
GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_TOGGLE_BUTTON, GailToggleButton, gail_toggle_button, GTK_TYPE_TOGGLE_BUTTON)
GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_IMAGE, GailImage, gail_image, GTK_TYPE_IMAGE)
-GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_TEXT_VIEW, GailTextView, gail_text_view, GTK_TYPE_TEXT_VIEW)
GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_COMBO_BOX, GailComboBox, gail_combo_box, GTK_TYPE_COMBO_BOX)
GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_MENU_SHELL, GailMenuShell, gail_menu_shell, GTK_TYPE_MENU_SHELL)
GAIL_IMPLEMENT_FACTORY (GAIL_TYPE_MENU, GailMenu, gail_menu, GTK_TYPE_MENU)
GAIL_WIDGET_SET_FACTORY (GTK_TYPE_MENU_ITEM, gail_menu_item);
GAIL_WIDGET_SET_FACTORY (GTK_TYPE_TOGGLE_BUTTON, gail_toggle_button);
GAIL_WIDGET_SET_FACTORY (GTK_TYPE_IMAGE, gail_image);
- GAIL_WIDGET_SET_FACTORY (GTK_TYPE_TEXT_VIEW, gail_text_view);
GAIL_WIDGET_SET_FACTORY (GTK_TYPE_COMBO_BOX, gail_combo_box);
GAIL_WIDGET_SET_FACTORY (GTK_TYPE_MENU_BAR, gail_menu_shell);
GAIL_WIDGET_SET_FACTORY (GTK_TYPE_MENU, gail_menu);
+++ /dev/null
-/* GAIL - The GNOME Accessibility Implementation Library
- * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdlib.h>
-#include <glib-object.h>
-#include <glib/gstdio.h>
-#include <gtk/gtk.h>
-#include "gailtextview.h"
-#include <libgail-util/gailmisc.h>
-
-static void gail_text_view_class_init (GailTextViewClass *klass);
-static void gail_text_view_init (GailTextView *text_view);
-
-static void gail_text_view_real_initialize (AtkObject *obj,
- gpointer data);
-static void gail_text_view_real_notify_gtk (GObject *obj,
- GParamSpec *pspec);
-
-static void gail_text_view_finalize (GObject *object);
-
-static void atk_text_interface_init (AtkTextIface *iface);
-
-/* atkobject.h */
-
-static AtkStateSet* gail_text_view_ref_state_set (AtkObject *accessible);
-
-/* atktext.h */
-
-static gchar* gail_text_view_get_text_after_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset);
-static gchar* gail_text_view_get_text_at_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset);
-static gchar* gail_text_view_get_text_before_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset);
-static gchar* gail_text_view_get_text (AtkText*text,
- gint start_offset,
- gint end_offset);
-static gunichar gail_text_view_get_character_at_offset (AtkText *text,
- gint offset);
-static gint gail_text_view_get_character_count (AtkText *text);
-static gint gail_text_view_get_caret_offset (AtkText *text);
-static gboolean gail_text_view_set_caret_offset (AtkText *text,
- gint offset);
-static gint gail_text_view_get_offset_at_point (AtkText *text,
- gint x,
- gint y,
- AtkCoordType coords);
-static gint gail_text_view_get_n_selections (AtkText *text);
-static gchar* gail_text_view_get_selection (AtkText *text,
- gint selection_num,
- gint *start_offset,
- gint *end_offset);
-static gboolean gail_text_view_add_selection (AtkText *text,
- gint start_offset,
- gint end_offset);
-static gboolean gail_text_view_remove_selection (AtkText *text,
- gint selection_num);
-static gboolean gail_text_view_set_selection (AtkText *text,
- gint selection_num,
- gint start_offset,
- gint end_offset);
-static void gail_text_view_get_character_extents (AtkText *text,
- gint offset,
- gint *x,
- gint *y,
- gint *width,
- gint *height,
- AtkCoordType coords);
-static AtkAttributeSet * gail_text_view_get_run_attributes
- (AtkText *text,
- gint offset,
- gint *start_offset,
- gint *end_offset);
-static AtkAttributeSet * gail_text_view_get_default_attributes
- (AtkText *text);
-/* atkeditabletext.h */
-
-static void atk_editable_text_interface_init (AtkEditableTextIface *iface);
-static gboolean gail_text_view_set_run_attributes (AtkEditableText *text,
- AtkAttributeSet *attrib_set,
- gint start_offset,
- gint end_offset);
-static void gail_text_view_set_text_contents (AtkEditableText *text,
- const gchar *string);
-static void gail_text_view_insert_text (AtkEditableText *text,
- const gchar *string,
- gint length,
- gint *position);
-static void gail_text_view_copy_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos);
-static void gail_text_view_cut_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos);
-static void gail_text_view_delete_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos);
-static void gail_text_view_paste_text (AtkEditableText *text,
- gint position);
-static void gail_text_view_paste_received (GtkClipboard *clipboard,
- const gchar *text,
- gpointer data);
-/* AtkStreamableContent */
-static void atk_streamable_content_interface_init (AtkStreamableContentIface *iface);
-static gint gail_streamable_content_get_n_mime_types (AtkStreamableContent *streamable);
-static const gchar* gail_streamable_content_get_mime_type (AtkStreamableContent *streamable,
- gint i);
-static GIOChannel* gail_streamable_content_get_stream (AtkStreamableContent *streamable,
- const gchar *mime_type);
-/* getURI requires atk-1.12.0 or later
-static void gail_streamable_content_get_uri (AtkStreamableContent *streamable);
-*/
-
-/* Callbacks */
-
-static void _gail_text_view_insert_text_cb (GtkTextBuffer *buffer,
- GtkTextIter *arg1,
- gchar *arg2,
- gint arg3,
- gpointer user_data);
-static void _gail_text_view_delete_range_cb (GtkTextBuffer *buffer,
- GtkTextIter *arg1,
- GtkTextIter *arg2,
- gpointer user_data);
-static void _gail_text_view_changed_cb (GtkTextBuffer *buffer,
- gpointer user_data);
-static void _gail_text_view_mark_set_cb (GtkTextBuffer *buffer,
- GtkTextIter *arg1,
- GtkTextMark *arg2,
- gpointer user_data);
-static gchar* get_text_near_offset (AtkText *text,
- GailOffsetType function,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset);
-static gint get_insert_offset (GtkTextBuffer *buffer);
-static gint get_selection_bound (GtkTextBuffer *buffer);
-static void emit_text_caret_moved (GailTextView *gail_text_view,
- gint insert_offset);
-static gint insert_idle_handler (gpointer data);
-
-typedef struct _GailTextViewPaste GailTextViewPaste;
-
-struct _GailTextViewPaste
-{
- GtkTextBuffer* buffer;
- gint position;
-};
-
-G_DEFINE_TYPE_WITH_CODE (GailTextView, gail_text_view, GAIL_TYPE_CONTAINER,
- G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
- G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
- G_IMPLEMENT_INTERFACE (ATK_TYPE_STREAMABLE_CONTENT, atk_streamable_content_interface_init))
-
-static void
-gail_text_view_class_init (GailTextViewClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
- GailWidgetClass *widget_class;
-
- widget_class = (GailWidgetClass*)klass;
-
- gobject_class->finalize = gail_text_view_finalize;
-
- class->ref_state_set = gail_text_view_ref_state_set;
- class->initialize = gail_text_view_real_initialize;
-
- widget_class->notify_gtk = gail_text_view_real_notify_gtk;
-}
-
-static void
-gail_text_view_init (GailTextView *text_view)
-{
- text_view->textutil = NULL;
- text_view->signal_name = NULL;
- text_view->previous_insert_offset = -1;
- text_view->previous_selection_bound = -1;
- text_view->insert_notify_handler = 0;
-}
-
-static void
-setup_buffer (GtkTextView *view,
- GailTextView *gail_view)
-{
- GtkTextBuffer *buffer;
-
- buffer = gtk_text_view_get_buffer (view);
-
- if (gail_view->textutil)
- g_object_unref (gail_view->textutil);
-
- gail_view->textutil = gail_text_util_new ();
- gail_text_util_buffer_setup (gail_view->textutil, buffer);
-
- /* Set up signal callbacks */
- g_signal_connect_data (buffer, "insert-text",
- (GCallback) _gail_text_view_insert_text_cb, view, NULL, 0);
- g_signal_connect_data (buffer, "delete-range",
- (GCallback) _gail_text_view_delete_range_cb, view, NULL, 0);
- g_signal_connect_data (buffer, "mark-set",
- (GCallback) _gail_text_view_mark_set_cb, view, NULL, 0);
- g_signal_connect_data (buffer, "changed",
- (GCallback) _gail_text_view_changed_cb, view, NULL, 0);
-
-}
-
-static void
-gail_text_view_real_initialize (AtkObject *obj,
- gpointer data)
-{
- GtkTextView *view;
- GailTextView *gail_view;
-
- ATK_OBJECT_CLASS (gail_text_view_parent_class)->initialize (obj, data);
-
- view = GTK_TEXT_VIEW (data);
-
- gail_view = GAIL_TEXT_VIEW (obj);
- setup_buffer (view, gail_view);
-
- obj->role = ATK_ROLE_TEXT;
-
-}
-
-static void
-gail_text_view_finalize (GObject *object)
-{
- GailTextView *text_view = GAIL_TEXT_VIEW (object);
-
- g_object_unref (text_view->textutil);
- if (text_view->insert_notify_handler)
- g_source_remove (text_view->insert_notify_handler);
-
- G_OBJECT_CLASS (gail_text_view_parent_class)->finalize (object);
-}
-
-static void
-gail_text_view_real_notify_gtk (GObject *obj,
- GParamSpec *pspec)
-{
- if (!strcmp (pspec->name, "editable"))
- {
- AtkObject *atk_obj;
- gboolean editable;
-
- atk_obj = gtk_widget_get_accessible (GTK_WIDGET (obj));
- editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (obj));
- atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE,
- editable);
- }
- else if (!strcmp (pspec->name, "buffer"))
- {
- AtkObject *atk_obj;
-
- atk_obj = gtk_widget_get_accessible (GTK_WIDGET (obj));
- setup_buffer (GTK_TEXT_VIEW (obj), GAIL_TEXT_VIEW (atk_obj));
- }
- else
- GAIL_WIDGET_CLASS (gail_text_view_parent_class)->notify_gtk (obj, pspec);
-}
-
-/* atkobject.h */
-
-static AtkStateSet*
-gail_text_view_ref_state_set (AtkObject *accessible)
-{
- AtkStateSet *state_set;
- GtkTextView *text_view;
- GtkWidget *widget;
-
- state_set = ATK_OBJECT_CLASS (gail_text_view_parent_class)->ref_state_set (accessible);
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
-
- if (widget == NULL)
- return state_set;
-
- text_view = GTK_TEXT_VIEW (widget);
-
- if (gtk_text_view_get_editable (text_view))
- atk_state_set_add_state (state_set, ATK_STATE_EDITABLE);
- atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
-
- return state_set;
-}
-
-/* atktext.h */
-
-static void
-atk_text_interface_init (AtkTextIface *iface)
-{
- iface->get_text = gail_text_view_get_text;
- iface->get_text_after_offset = gail_text_view_get_text_after_offset;
- iface->get_text_at_offset = gail_text_view_get_text_at_offset;
- iface->get_text_before_offset = gail_text_view_get_text_before_offset;
- iface->get_character_at_offset = gail_text_view_get_character_at_offset;
- iface->get_character_count = gail_text_view_get_character_count;
- iface->get_caret_offset = gail_text_view_get_caret_offset;
- iface->set_caret_offset = gail_text_view_set_caret_offset;
- iface->get_offset_at_point = gail_text_view_get_offset_at_point;
- iface->get_character_extents = gail_text_view_get_character_extents;
- iface->get_n_selections = gail_text_view_get_n_selections;
- iface->get_selection = gail_text_view_get_selection;
- iface->add_selection = gail_text_view_add_selection;
- iface->remove_selection = gail_text_view_remove_selection;
- iface->set_selection = gail_text_view_set_selection;
- iface->get_run_attributes = gail_text_view_get_run_attributes;
- iface->get_default_attributes = gail_text_view_get_default_attributes;
-}
-
-static gchar*
-gail_text_view_get_text (AtkText *text,
- gint start_offset,
- gint end_offset)
-{
- GtkTextView *view;
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- GtkWidget *widget;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return NULL;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
- gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
- gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset);
-
- return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
-}
-
-static gchar*
-gail_text_view_get_text_after_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- GtkWidget *widget;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return NULL;
-
- return get_text_near_offset (text, GAIL_AFTER_OFFSET,
- boundary_type, offset,
- start_offset, end_offset);
-}
-
-static gchar*
-gail_text_view_get_text_at_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- GtkWidget *widget;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return NULL;
-
- return get_text_near_offset (text, GAIL_AT_OFFSET,
- boundary_type, offset,
- start_offset, end_offset);
-}
-
-static gchar*
-gail_text_view_get_text_before_offset (AtkText *text,
- gint offset,
- AtkTextBoundary boundary_type,
- gint *start_offset,
- gint *end_offset)
-{
- GtkWidget *widget;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return NULL;
-
- return get_text_near_offset (text, GAIL_BEFORE_OFFSET,
- boundary_type, offset,
- start_offset, end_offset);
-}
-
-static gunichar
-gail_text_view_get_character_at_offset (AtkText *text,
- gint offset)
-{
- GtkWidget *widget;
- GtkTextIter start, end;
- GtkTextBuffer *buffer;
- gchar *string;
- gunichar unichar;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- return '\0';
-
- buffer = GAIL_TEXT_VIEW (text)->textutil->buffer;
- if (offset >= gtk_text_buffer_get_char_count (buffer))
- return '\0';
-
- gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
- end = start;
- gtk_text_iter_forward_char (&end);
- string = gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
- unichar = g_utf8_get_char (string);
- g_free(string);
- return unichar;
-}
-
-static gint
-gail_text_view_get_character_count (AtkText *text)
-{
- GtkTextView *view;
- GtkTextBuffer *buffer;
- GtkWidget *widget;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return 0;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
- return gtk_text_buffer_get_char_count (buffer);
-}
-
-static gint
-gail_text_view_get_caret_offset (AtkText *text)
-{
- GtkTextView *view;
- GtkWidget *widget;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return 0;
-
- view = GTK_TEXT_VIEW (widget);
- return get_insert_offset (gtk_text_view_get_buffer (view));
-}
-
-static gboolean
-gail_text_view_set_caret_offset (AtkText *text,
- gint offset)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter pos_itr;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return FALSE;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, offset);
- gtk_text_buffer_place_cursor (buffer, &pos_itr);
- gtk_text_view_scroll_to_iter (view, &pos_itr, 0, FALSE, 0, 0);
- return TRUE;
-}
-
-static gint
-gail_text_view_get_offset_at_point (AtkText *text,
- gint x,
- gint y,
- AtkCoordType coords)
-{
- GtkTextView *view;
- GtkTextIter loc_itr;
- gint x_widget, y_widget, x_window, y_window, buff_x, buff_y;
- GtkWidget *widget;
- GdkWindow *window;
- GdkRectangle rect;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return -1;
-
- view = GTK_TEXT_VIEW (widget);
-
- window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_WIDGET);
- gdk_window_get_origin (window, &x_widget, &y_widget);
-
- if (coords == ATK_XY_SCREEN)
- {
- x = x - x_widget;
- y = y - y_widget;
- }
- else if (coords == ATK_XY_WINDOW)
- {
- window = gdk_window_get_toplevel (window);
- gdk_window_get_origin (window, &x_window, &y_window);
-
- x = x - x_widget + x_window;
- y = y - y_widget + y_window;
- }
- else
- return -1;
-
- gtk_text_view_window_to_buffer_coords (view, GTK_TEXT_WINDOW_WIDGET,
- x, y, &buff_x, &buff_y);
- gtk_text_view_get_visible_rect (view, &rect);
- /*
- * Clamp point to visible rectangle
- */
- buff_x = CLAMP (buff_x, rect.x, rect.x + rect.width - 1);
- buff_y = CLAMP (buff_y, rect.y, rect.y + rect.height - 1);
-
- gtk_text_view_get_iter_at_location (view, &loc_itr, buff_x, buff_y);
- /*
- * The iter at a location sometimes points to the next character.
- * See bug 111031. We work around that
- */
- gtk_text_view_get_iter_location (view, &loc_itr, &rect);
- if (buff_x < rect.x)
- gtk_text_iter_backward_char (&loc_itr);
- return gtk_text_iter_get_offset (&loc_itr);
-}
-
-static void
-gail_text_view_get_character_extents (AtkText *text,
- gint offset,
- gint *x,
- gint *y,
- gint *width,
- gint *height,
- AtkCoordType coords)
-{
- GtkTextView *view;
- GtkTextBuffer *buffer;
- GtkTextIter iter;
- GtkWidget *widget;
- GdkRectangle rectangle;
- GdkWindow *window;
- gint x_widget, y_widget, x_window, y_window;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
- gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
- gtk_text_view_get_iter_location (view, &iter, &rectangle);
-
- window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_WIDGET);
- gdk_window_get_origin (window, &x_widget, &y_widget);
-
- *height = rectangle.height;
- *width = rectangle.width;
-
- gtk_text_view_buffer_to_window_coords (view, GTK_TEXT_WINDOW_WIDGET,
- rectangle.x, rectangle.y, x, y);
- if (coords == ATK_XY_WINDOW)
- {
- window = gdk_window_get_toplevel (window);
- gdk_window_get_origin (window, &x_window, &y_window);
- *x += x_widget - x_window;
- *y += y_widget - y_window;
- }
- else if (coords == ATK_XY_SCREEN)
- {
- *x += x_widget;
- *y += y_widget;
- }
- else
- {
- *x = 0;
- *y = 0;
- *height = 0;
- *width = 0;
- }
-}
-
-static AtkAttributeSet*
-gail_text_view_get_run_attributes (AtkText *text,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- GtkTextView *view;
- GtkTextBuffer *buffer;
- GtkWidget *widget;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return NULL;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- return gail_misc_buffer_get_run_attributes (buffer, offset,
- start_offset, end_offset);
-}
-
-static AtkAttributeSet*
-add_text_attribute (AtkAttributeSet *attrib_set, AtkTextAttribute attr, gint i)
-{
- const gchar *value;
-
- value = atk_text_attribute_get_value (attr, i);
-
- return gail_misc_add_attribute (attrib_set, i, g_strdup (value));
-}
-
-static AtkAttributeSet*
-gail_text_view_get_default_attributes (AtkText *text)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextAttributes *text_attrs;
- AtkAttributeSet *attrib_set = NULL;
- PangoFontDescription *font;
- gchar *value;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return NULL;
-
- view = GTK_TEXT_VIEW (widget);
- text_attrs = gtk_text_view_get_default_attributes (view);
-
- font = text_attrs->font;
-
- if (font)
- {
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_STYLE,
- pango_font_description_get_style (font));
-
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_VARIANT,
- pango_font_description_get_variant (font));
-
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_STRETCH,
- pango_font_description_get_stretch (font));
-
- value = g_strdup (pango_font_description_get_family (font));
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_FAMILY_NAME, value);
-
- value = g_strdup_printf ("%d", pango_font_description_get_weight (font));
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_WEIGHT, value);
-
- value = g_strdup_printf ("%i", pango_font_description_get_size (font) / PANGO_SCALE);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_SIZE, value);
- }
-
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_JUSTIFICATION, text_attrs->justification);
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_DIRECTION, text_attrs->direction);
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_WRAP_MODE, text_attrs->wrap_mode);
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_EDITABLE, text_attrs->editable);
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_INVISIBLE, text_attrs->invisible);
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_BG_FULL_HEIGHT, text_attrs->bg_full_height);
-
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_STRIKETHROUGH,
- text_attrs->appearance.strikethrough);
- attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_UNDERLINE,
- text_attrs->appearance.underline);
-
- value = g_strdup_printf ("%u,%u,%u",
- text_attrs->appearance.bg_color.red,
- text_attrs->appearance.bg_color.green,
- text_attrs->appearance.bg_color.blue);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_BG_COLOR, value);
-
- value = g_strdup_printf ("%u,%u,%u",
- text_attrs->appearance.fg_color.red,
- text_attrs->appearance.fg_color.green,
- text_attrs->appearance.fg_color.blue);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_FG_COLOR, value);
-
- value = g_strdup_printf ("%g", text_attrs->font_scale);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_SCALE, value);
-
- value = g_strdup ((gchar *)(text_attrs->language));
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_LANGUAGE, value);
-
- value = g_strdup_printf ("%i", text_attrs->appearance.rise);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_RISE, value);
-
- value = g_strdup_printf ("%i", text_attrs->pixels_inside_wrap);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP, value);
-
- value = g_strdup_printf ("%i", text_attrs->pixels_below_lines);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES, value);
-
- value = g_strdup_printf ("%i", text_attrs->pixels_above_lines);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES, value);
-
- value = g_strdup_printf ("%i", text_attrs->indent);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_INDENT, value);
-
- value = g_strdup_printf ("%i", text_attrs->left_margin);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_LEFT_MARGIN, value);
-
- value = g_strdup_printf ("%i", text_attrs->right_margin);
- attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_RIGHT_MARGIN, value);
-
- gtk_text_attributes_unref (text_attrs);
- return attrib_set;
-}
-
-static gint
-gail_text_view_get_n_selections (AtkText *text)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- gint select_start, select_end;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return -1;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
- select_start = gtk_text_iter_get_offset (&start);
- select_end = gtk_text_iter_get_offset (&end);
-
- if (select_start != select_end)
- return 1;
- else
- return 0;
-}
-
-static gchar*
-gail_text_view_get_selection (AtkText *text,
- gint selection_num,
- gint *start_pos,
- gint *end_pos)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return NULL;
-
- /* Only let the user get the selection if one is set, and if the
- * selection_num is 0.
- */
- if (selection_num != 0)
- return NULL;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
- *start_pos = gtk_text_iter_get_offset (&start);
- *end_pos = gtk_text_iter_get_offset (&end);
-
- if (*start_pos != *end_pos)
- return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
- else
- return NULL;
-}
-
-static gboolean
-gail_text_view_add_selection (AtkText *text,
- gint start_pos,
- gint end_pos)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter pos_itr;
- GtkTextIter start, end;
- gint select_start, select_end;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return FALSE;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
- select_start = gtk_text_iter_get_offset (&start);
- select_end = gtk_text_iter_get_offset (&end);
-
- /* If there is already a selection, then don't allow another to be added,
- * since GtkTextView only supports one selected region.
- */
- if (select_start == select_end)
- {
- gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, start_pos);
- gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &pos_itr);
- gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, end_pos);
- gtk_text_buffer_move_mark_by_name (buffer, "insert", &pos_itr);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-static gboolean
-gail_text_view_remove_selection (AtkText *text,
- gint selection_num)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextMark *cursor_mark;
- GtkTextIter cursor_itr;
- GtkTextIter start, end;
- gint select_start, select_end;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return FALSE;
-
- if (selection_num != 0)
- return FALSE;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
- select_start = gtk_text_iter_get_offset(&start);
- select_end = gtk_text_iter_get_offset(&end);
-
- if (select_start != select_end)
- {
- /* Setting the start & end of the selected region to the caret position
- * turns off the selection.
- */
- cursor_mark = gtk_text_buffer_get_insert (buffer);
- gtk_text_buffer_get_iter_at_mark (buffer, &cursor_itr, cursor_mark);
- gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &cursor_itr);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-static gboolean
-gail_text_view_set_selection (AtkText *text,
- gint selection_num,
- gint start_pos,
- gint end_pos)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter pos_itr;
- GtkTextIter start, end;
- gint select_start, select_end;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- {
- /* State is defunct */
- return FALSE;
- }
-
- /* Only let the user move the selection if one is set, and if the
- * selection_num is 0
- */
- if (selection_num != 0)
- return FALSE;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
- select_start = gtk_text_iter_get_offset(&start);
- select_end = gtk_text_iter_get_offset(&end);
-
- if (select_start != select_end)
- {
- gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, start_pos);
- gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &pos_itr);
- gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, end_pos);
- gtk_text_buffer_move_mark_by_name (buffer, "insert", &pos_itr);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/* atkeditabletext.h */
-
-static void
-atk_editable_text_interface_init (AtkEditableTextIface *iface)
-{
- iface->set_text_contents = gail_text_view_set_text_contents;
- iface->insert_text = gail_text_view_insert_text;
- iface->copy_text = gail_text_view_copy_text;
- iface->cut_text = gail_text_view_cut_text;
- iface->delete_text = gail_text_view_delete_text;
- iface->paste_text = gail_text_view_paste_text;
- iface->set_run_attributes = gail_text_view_set_run_attributes;
-}
-
-static gboolean
-gail_text_view_set_run_attributes (AtkEditableText *text,
- AtkAttributeSet *attrib_set,
- gint start_offset,
- gint end_offset)
-{
- GtkTextView *view;
- GtkTextBuffer *buffer;
- GtkWidget *widget;
- GtkTextTag *tag;
- GtkTextIter start;
- GtkTextIter end;
- gint j;
- GdkColor *color;
- gchar** RGB_vals;
- GSList *l;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return FALSE;
-
- view = GTK_TEXT_VIEW (widget);
- if (!gtk_text_view_get_editable (view))
- return FALSE;
-
- buffer = gtk_text_view_get_buffer (view);
-
- if (attrib_set == NULL)
- return FALSE;
-
- gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
- gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset);
-
- tag = gtk_text_buffer_create_tag (buffer, NULL, NULL);
-
- for (l = attrib_set; l; l = l->next)
- {
- gchar *name;
- gchar *value;
- AtkAttribute *at;
-
- at = l->data;
-
- name = at->name;
- value = at->value;
-
- if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_LEFT_MARGIN)))
- g_object_set (G_OBJECT (tag), "left_margin", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_RIGHT_MARGIN)))
- g_object_set (G_OBJECT (tag), "right_margin", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_INDENT)))
- g_object_set (G_OBJECT (tag), "indent", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_PIXELS_ABOVE_LINES)))
- g_object_set (G_OBJECT (tag), "pixels_above_lines", atoi (value), NULL);
-
- else if (!strcmp(name, atk_text_attribute_get_name (ATK_TEXT_ATTR_PIXELS_BELOW_LINES)))
- g_object_set (G_OBJECT (tag), "pixels_below_lines", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP)))
- g_object_set (G_OBJECT (tag), "pixels_inside_wrap", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_SIZE)))
- g_object_set (G_OBJECT (tag), "size", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_RISE)))
- g_object_set (G_OBJECT (tag), "rise", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_WEIGHT)))
- g_object_set (G_OBJECT (tag), "weight", atoi (value), NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_BG_FULL_HEIGHT)))
- {
- g_object_set (G_OBJECT (tag), "bg_full_height",
- (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_BG_FULL_HEIGHT, 0))),
- NULL);
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_LANGUAGE)))
- g_object_set (G_OBJECT (tag), "language", value, NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_FAMILY_NAME)))
- g_object_set (G_OBJECT (tag), "family", value, NULL);
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_EDITABLE)))
- {
- g_object_set (G_OBJECT (tag), "editable",
- (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_EDITABLE, 0))),
- NULL);
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_INVISIBLE)))
- {
- g_object_set (G_OBJECT (tag), "invisible",
- (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_EDITABLE, 0))),
- NULL);
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_UNDERLINE)))
- {
- for (j = 0; j < 3; j++)
- {
- if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_UNDERLINE, j)))
- {
- g_object_set (G_OBJECT (tag), "underline", j, NULL);
- break;
- }
- }
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_STRIKETHROUGH)))
- {
- g_object_set (G_OBJECT (tag), "strikethrough",
- (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_STRIKETHROUGH, 0))),
- NULL);
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_BG_COLOR)))
- {
- RGB_vals = g_strsplit (value, ",", 3);
- color = g_malloc (sizeof (GdkColor));
- color->red = atoi (RGB_vals[0]);
- color->green = atoi (RGB_vals[1]);
- color->blue = atoi (RGB_vals[2]);
- g_object_set (G_OBJECT (tag), "background_gdk", color, NULL);
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_FG_COLOR)))
- {
- RGB_vals = g_strsplit (value, ",", 3);
- color = g_malloc (sizeof (GdkColor));
- color->red = atoi (RGB_vals[0]);
- color->green = atoi (RGB_vals[1]);
- color->blue = atoi (RGB_vals[2]);
- g_object_set (G_OBJECT (tag), "foreground_gdk", color, NULL);
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_STRETCH)))
- {
- for (j = 0; j < 9; j++)
- {
- if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH, j)))
- {
- g_object_set (G_OBJECT (tag), "stretch", j, NULL);
- break;
- }
- }
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_JUSTIFICATION)))
- {
- for (j = 0; j < 4; j++)
- {
- if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION, j)))
- {
- g_object_set (G_OBJECT (tag), "justification", j, NULL);
- break;
- }
- }
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_DIRECTION)))
- {
- for (j = 0; j < 3; j++)
- {
- if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, j)))
- {
- g_object_set (G_OBJECT (tag), "direction", j, NULL);
- break;
- }
- }
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_VARIANT)))
- {
- for (j = 0; j < 2; j++)
- {
- if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT, j)))
- {
- g_object_set (G_OBJECT (tag), "variant", j, NULL);
- break;
- }
- }
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_WRAP_MODE)))
- {
- for (j = 0; j < 3; j++)
- {
- if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_WRAP_MODE, j)))
- {
- g_object_set (G_OBJECT (tag), "wrap_mode", j, NULL);
- break;
- }
- }
- }
-
- else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_STYLE)))
- {
- for (j = 0; j < 3; j++)
- {
- if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE, j)))
- {
- g_object_set (G_OBJECT (tag), "style", j, NULL);
- break;
- }
- }
- }
-
- else
- return FALSE;
- }
-
- gtk_text_buffer_apply_tag (buffer, tag, &start, &end);
-
- return TRUE;
-}
-
-static void
-gail_text_view_set_text_contents (AtkEditableText *text,
- const gchar *string)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return;
-
- view = GTK_TEXT_VIEW (widget);
- if (!gtk_text_view_get_editable (view))
- return;
- buffer = gtk_text_view_get_buffer (view);
-
- /* The -1 indicates that the input string must be null-terminated */
- gtk_text_buffer_set_text (buffer, string, -1);
-}
-
-static void
-gail_text_view_insert_text (AtkEditableText *text,
- const gchar *string,
- gint length,
- gint *position)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter pos_itr;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return;
-
- view = GTK_TEXT_VIEW (widget);
- if (!gtk_text_view_get_editable (view))
- return;
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, *position);
- gtk_text_buffer_insert (buffer, &pos_itr, string, length);
-}
-
-static void
-gail_text_view_copy_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- gchar *str;
- GtkClipboard *clipboard;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return;
-
- view = GTK_TEXT_VIEW (widget);
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_iter_at_offset (buffer, &start, start_pos);
- gtk_text_buffer_get_iter_at_offset (buffer, &end, end_pos);
- str = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
- clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
- GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, str, -1);
-}
-
-static void
-gail_text_view_cut_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter start, end;
- gchar *str;
- GtkClipboard *clipboard;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return;
-
- view = GTK_TEXT_VIEW (widget);
- if (!gtk_text_view_get_editable (view))
- return;
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_iter_at_offset (buffer, &start, start_pos);
- gtk_text_buffer_get_iter_at_offset (buffer, &end, end_pos);
- str = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
- clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
- GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text (clipboard, str, -1);
- gtk_text_buffer_delete (buffer, &start, &end);
-}
-
-static void
-gail_text_view_delete_text (AtkEditableText *text,
- gint start_pos,
- gint end_pos)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GtkTextIter start_itr;
- GtkTextIter end_itr;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return;
-
- view = GTK_TEXT_VIEW (widget);
- if (!gtk_text_view_get_editable (view))
- return;
- buffer = gtk_text_view_get_buffer (view);
-
- gtk_text_buffer_get_iter_at_offset (buffer, &start_itr, start_pos);
- gtk_text_buffer_get_iter_at_offset (buffer, &end_itr, end_pos);
- gtk_text_buffer_delete (buffer, &start_itr, &end_itr);
-}
-
-static void
-gail_text_view_paste_text (AtkEditableText *text,
- gint position)
-{
- GtkTextView *view;
- GtkWidget *widget;
- GtkTextBuffer *buffer;
- GailTextViewPaste paste_struct;
- GtkClipboard *clipboard;
-
- widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
- if (widget == NULL)
- /* State is defunct */
- return;
-
- view = GTK_TEXT_VIEW (widget);
- if (!gtk_text_view_get_editable (view))
- return;
- buffer = gtk_text_view_get_buffer (view);
-
- paste_struct.buffer = buffer;
- paste_struct.position = position;
-
- g_object_ref (paste_struct.buffer);
- clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
- GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_request_text (clipboard,
- gail_text_view_paste_received, &paste_struct);
-}
-
-static void
-gail_text_view_paste_received (GtkClipboard *clipboard,
- const gchar *text,
- gpointer data)
-{
- GailTextViewPaste* paste_struct = (GailTextViewPaste *)data;
- GtkTextIter pos_itr;
-
- if (text)
- {
- gtk_text_buffer_get_iter_at_offset (paste_struct->buffer, &pos_itr,
- paste_struct->position);
- gtk_text_buffer_insert (paste_struct->buffer, &pos_itr, text, -1);
- }
-
- g_object_unref (paste_struct->buffer);
-}
-
-/* Callbacks */
-
-/* Note arg1 returns the start of the insert range, arg3 returns the
- * end of the insert range if multiple characters are inserted. If one
- * character is inserted they have the same value, which is the caret
- * location. arg2 returns the begin location of the insert.
- */
-static void
-_gail_text_view_insert_text_cb (GtkTextBuffer *buffer,
- GtkTextIter *arg1,
- gchar *arg2,
- gint arg3,
- gpointer user_data)
-{
- GtkTextView *text = (GtkTextView *) user_data;
- AtkObject *accessible;
- GailTextView *gail_text_view;
- gint position;
- gint length;
-
- g_return_if_fail (arg3 > 0);
-
- accessible = gtk_widget_get_accessible(GTK_WIDGET(text));
- gail_text_view = GAIL_TEXT_VIEW (accessible);
-
- gail_text_view->signal_name = "text_changed::insert";
- position = gtk_text_iter_get_offset (arg1);
- length = g_utf8_strlen(arg2, arg3);
-
- if (gail_text_view->length == 0)
- {
- gail_text_view->position = position;
- gail_text_view->length = length;
- }
- else if (gail_text_view->position + gail_text_view->length == position)
- {
- gail_text_view->length += length;
- }
- else
- {
- /*
- * We have a non-contiguous insert so report what we have
- */
- if (gail_text_view->insert_notify_handler)
- {
- g_source_remove (gail_text_view->insert_notify_handler);
- }
- gail_text_view->insert_notify_handler = 0;
- insert_idle_handler (gail_text_view);
- gail_text_view->position = position;
- gail_text_view->length = length;
- }
-
- /*
- * The signal will be emitted when the changed signal is received
- */
-}
-
-/* Note arg1 returns the start of the delete range, arg2 returns the
- * end of the delete range if multiple characters are deleted. If one
- * character is deleted they have the same value, which is the caret
- * location.
- */
-static void
-_gail_text_view_delete_range_cb (GtkTextBuffer *buffer,
- GtkTextIter *arg1,
- GtkTextIter *arg2,
- gpointer user_data)
-{
- GtkTextView *text = (GtkTextView *) user_data;
- AtkObject *accessible;
- GailTextView *gail_text_view;
- gint offset = gtk_text_iter_get_offset (arg1);
- gint length = gtk_text_iter_get_offset (arg2) - offset;
-
- accessible = gtk_widget_get_accessible(GTK_WIDGET(text));
- gail_text_view = GAIL_TEXT_VIEW (accessible);
- if (gail_text_view->insert_notify_handler)
- {
- g_source_remove (gail_text_view->insert_notify_handler);
- gail_text_view->insert_notify_handler = 0;
- if (gail_text_view->position == offset &&
- gail_text_view->length == length)
- {
- /*
- * Do not bother with insert and delete notifications
- */
- gail_text_view->signal_name = NULL;
- gail_text_view->position = 0;
- gail_text_view->length = 0;
- return;
- }
-
- insert_idle_handler (gail_text_view);
- }
- g_signal_emit_by_name (accessible, "text_changed::delete",
- offset, length);
-}
-
-/* Note arg1 and arg2 point to the same offset, which is the caret
- * position after the move
- */
-static void
-_gail_text_view_mark_set_cb (GtkTextBuffer *buffer,
- GtkTextIter *arg1,
- GtkTextMark *arg2,
- gpointer user_data)
-{
- GtkTextView *text = (GtkTextView *) user_data;
- AtkObject *accessible;
- GailTextView *gail_text_view;
- const char *mark_name = gtk_text_mark_get_name(arg2);
-
- accessible = gtk_widget_get_accessible(GTK_WIDGET(text));
- gail_text_view = GAIL_TEXT_VIEW (accessible);
-
- /*
- * Only generate the signal for the "insert" mark, which
- * represents the cursor.
- */
- if (mark_name && !strcmp(mark_name, "insert"))
- {
- int insert_offset, selection_bound;
- gboolean selection_changed;
-
- insert_offset = gtk_text_iter_get_offset (arg1);
-
- selection_bound = get_selection_bound (buffer);
- if (selection_bound != insert_offset)
- {
- if (selection_bound != gail_text_view->previous_selection_bound ||
- insert_offset != gail_text_view->previous_insert_offset)
- {
- selection_changed = TRUE;
- }
- else
- {
- selection_changed = FALSE;
- }
- }
- else if (gail_text_view->previous_selection_bound != gail_text_view->previous_insert_offset)
- {
- selection_changed = TRUE;
- }
- else
- {
- selection_changed = FALSE;
- }
-
- emit_text_caret_moved (gail_text_view, insert_offset);
- /*
- * insert and selection_bound marks are different to a selection
- * has changed
- */
- if (selection_changed)
- g_signal_emit_by_name (accessible, "text_selection_changed");
- gail_text_view->previous_selection_bound = selection_bound;
- }
-}
-
-static void
-_gail_text_view_changed_cb (GtkTextBuffer *buffer,
- gpointer user_data)
-{
- GtkTextView *text = (GtkTextView *) user_data;
- AtkObject *accessible;
- GailTextView *gail_text_view;
-
- accessible = gtk_widget_get_accessible (GTK_WIDGET (text));
- gail_text_view = GAIL_TEXT_VIEW (accessible);
- if (gail_text_view->signal_name)
- {
- if (!gail_text_view->insert_notify_handler)
- {
- gail_text_view->insert_notify_handler = gdk_threads_add_idle (insert_idle_handler, accessible);
- }
- return;
- }
- emit_text_caret_moved (gail_text_view, get_insert_offset (buffer));
- gail_text_view->previous_selection_bound = get_selection_bound (buffer);
-}
-
-static gchar*
-get_text_near_offset (AtkText *text,
- GailOffsetType function,
- AtkTextBoundary boundary_type,
- gint offset,
- gint *start_offset,
- gint *end_offset)
-{
- GtkTextView *view;
- gpointer layout = NULL;
-
- view = GTK_TEXT_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (text)));
-
- /*
- * Pass the GtkTextView to the function gail_text_util_get_text()
- * so it can find the start and end of the current line on the display.
- */
- if (boundary_type == ATK_TEXT_BOUNDARY_LINE_START ||
- boundary_type == ATK_TEXT_BOUNDARY_LINE_END)
- layout = view;
-
- return gail_text_util_get_text (GAIL_TEXT_VIEW (text)->textutil, layout,
- function, boundary_type, offset,
- start_offset, end_offset);
-}
-
-static gint
-get_insert_offset (GtkTextBuffer *buffer)
-{
- GtkTextMark *cursor_mark;
- GtkTextIter cursor_itr;
-
- cursor_mark = gtk_text_buffer_get_insert (buffer);
- gtk_text_buffer_get_iter_at_mark (buffer, &cursor_itr, cursor_mark);
- return gtk_text_iter_get_offset (&cursor_itr);
-}
-
-static gint
-get_selection_bound (GtkTextBuffer *buffer)
-{
- GtkTextMark *selection_mark;
- GtkTextIter selection_itr;
-
- selection_mark = gtk_text_buffer_get_selection_bound (buffer);
- gtk_text_buffer_get_iter_at_mark (buffer, &selection_itr, selection_mark);
- return gtk_text_iter_get_offset (&selection_itr);
-}
-
-static void
-emit_text_caret_moved (GailTextView *gail_text_view,
- gint insert_offset)
-{
- /*
- * If we have text which has been inserted notify the user
- */
- if (gail_text_view->insert_notify_handler)
- {
- g_source_remove (gail_text_view->insert_notify_handler);
- gail_text_view->insert_notify_handler = 0;
- insert_idle_handler (gail_text_view);
- }
-
- if (insert_offset != gail_text_view->previous_insert_offset)
- {
- /*
- * If the caret position has not changed then don't bother notifying
- *
- * When mouse click is used to change caret position, notification
- * is received on button down and button up.
- */
- g_signal_emit_by_name (gail_text_view, "text_caret_moved", insert_offset);
- gail_text_view->previous_insert_offset = insert_offset;
- }
-}
-
-static gint
-insert_idle_handler (gpointer data)
-{
- GailTextView *gail_text_view;
- GtkTextBuffer *buffer;
-
- gail_text_view = GAIL_TEXT_VIEW (data);
-
- g_signal_emit_by_name (data,
- gail_text_view->signal_name,
- gail_text_view->position,
- gail_text_view->length);
- gail_text_view->signal_name = NULL;
- gail_text_view->position = 0;
- gail_text_view->length = 0;
-
- buffer = gail_text_view->textutil->buffer;
- if (gail_text_view->insert_notify_handler)
- {
- /*
- * If called from idle handler notify caret moved
- */
- gail_text_view->insert_notify_handler = 0;
- emit_text_caret_moved (gail_text_view, get_insert_offset (buffer));
- gail_text_view->previous_selection_bound = get_selection_bound (buffer);
- }
-
- return FALSE;
-}
-
-static void
-atk_streamable_content_interface_init (AtkStreamableContentIface *iface)
-{
- iface->get_n_mime_types = gail_streamable_content_get_n_mime_types;
- iface->get_mime_type = gail_streamable_content_get_mime_type;
- iface->get_stream = gail_streamable_content_get_stream;
-}
-
-static gint gail_streamable_content_get_n_mime_types (AtkStreamableContent *streamable)
-{
- gint n_mime_types = 0;
-
- if (GAIL_IS_TEXT_VIEW (streamable) && GAIL_TEXT_VIEW (streamable)->textutil)
- {
- int i;
- gboolean advertises_plaintext = FALSE;
- GdkAtom *atoms =
- gtk_text_buffer_get_serialize_formats (
- GAIL_TEXT_VIEW (streamable)->textutil->buffer,
- &n_mime_types);
- for (i = 0; i < n_mime_types-1; ++i)
- if (!strcmp ("text/plain", gdk_atom_name (atoms[i])))
- advertises_plaintext = TRUE;
- if (!advertises_plaintext) ++n_mime_types;
- /* we support text/plain even if the GtkTextBuffer doesn't */
- }
- return n_mime_types;
-}
-
-static const gchar*
-gail_streamable_content_get_mime_type (AtkStreamableContent *streamable, gint i)
-{
- if (GAIL_IS_TEXT_VIEW (streamable) && GAIL_TEXT_VIEW (streamable)->textutil)
- {
- gint n_mime_types = 0;
- GdkAtom *atoms;
- atoms = gtk_text_buffer_get_serialize_formats (
- GAIL_TEXT_VIEW (streamable)->textutil->buffer,
- &n_mime_types);
- if (i < n_mime_types)
- {
- return gdk_atom_name (atoms [i]);
- }
- else if (i == n_mime_types)
- return "text/plain";
- }
- return NULL;
-}
-
-static GIOChannel* gail_streamable_content_get_stream (AtkStreamableContent *streamable,
- const gchar *mime_type)
-{
- gint i, n_mime_types = 0;
- GdkAtom *atoms;
- if (!GAIL_IS_TEXT_VIEW (streamable) || !GAIL_TEXT_VIEW (streamable)->textutil)
- return NULL;
- atoms = gtk_text_buffer_get_serialize_formats (
- GAIL_TEXT_VIEW (streamable)->textutil->buffer,
- &n_mime_types);
- for (i = 0; i < n_mime_types; ++i)
- {
- if (!strcmp ("text/plain", mime_type) ||
- !strcmp (gdk_atom_name (atoms[i]), mime_type)) {
- GtkTextBuffer *buffer;
- guint8 *cbuf;
- GError *err = NULL;
- gsize len, written;
- gchar tname[80];
- GtkTextIter start, end;
- GIOChannel *gio = NULL;
- int fd;
- buffer = GAIL_TEXT_VIEW (streamable)->textutil->buffer;
- gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
- gtk_text_buffer_get_iter_at_offset (buffer, &end, -1);
- if (!strcmp ("text/plain", mime_type))
- {
- cbuf = (guint8*) gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
- len = strlen ((const char *) cbuf);
- }
- else
- {
- cbuf = gtk_text_buffer_serialize (buffer, buffer, atoms[i], &start, &end, &len);
- }
- g_snprintf (tname, 20, "streamXXXXXX");
- fd = g_mkstemp (tname);
- gio = g_io_channel_unix_new (fd);
- g_io_channel_set_encoding (gio, NULL, &err);
- if (!err) g_io_channel_write_chars (gio, (const char *) cbuf, (gssize) len, &written, &err);
- else g_message ("%s", err->message);
- if (!err) g_io_channel_seek_position (gio, 0, G_SEEK_SET, &err);
- else g_message ("%s", err->message);
- if (!err) g_io_channel_flush (gio, &err);
- else g_message ("%s", err->message);
- if (err) {
- g_message ("<error writing to stream [%s]>", tname);
- g_error_free (err);
- }
- /* make sure the file is removed on unref of the giochannel */
- else {
- g_unlink (tname);
- return gio;
- }
- }
- }
- return NULL;
-}
-
+++ /dev/null
-/* GAIL - The GNOME Accessibility Implementation Library
- * Copyright 2001 Sun Microsystems Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __GAIL_TEXT_VIEW_H__
-#define __GAIL_TEXT_VIEW_H__
-
-#include "gailcontainer.h"
-#include "gailtextutil.h"
-
-G_BEGIN_DECLS
-
-#define GAIL_TYPE_TEXT_VIEW (gail_text_view_get_type ())
-#define GAIL_TEXT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAIL_TYPE_TEXT_VIEW, GailTextView))
-#define GAIL_TEXT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAIL_TYPE_TEXT_VIEW, GailTextViewClass))
-#define GAIL_IS_TEXT_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAIL_TYPE_TEXT_VIEW))
-#define GAIL_IS_TEXT_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAIL_TYPE_TEXT_VIEW))
-#define GAIL_TEXT_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAIL_TYPE_TEXT_VIEW, GailTextViewClass))
-
-typedef struct _GailTextView GailTextView;
-typedef struct _GailTextViewClass GailTextViewClass;
-
-struct _GailTextView
-{
- GailContainer parent;
-
- GailTextUtil *textutil;
- gint previous_insert_offset;
- gint previous_selection_bound;
- /*
- * These fields store information about text changed
- */
- gchar *signal_name;
- gint position;
- gint length;
-
- guint insert_notify_handler;
-};
-
-GType gail_text_view_get_type (void);
-
-struct _GailTextViewClass
-{
- GailContainerClass parent_class;
-};
-
-G_END_DECLS
-
-#endif /* __GAIL_TEXT_VIEW_H__ */
--- /dev/null
+/* GAIL - The GNOME Accessibility Implementation Library
+ * Copyright 2001, 2002, 2003 Sun Microsystems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <glib-object.h>
+#include <glib/gstdio.h>
+#include <gtk/gtk.h>
+#include "gtktextviewaccessible.h"
+#include <libgail-util/gailmisc.h>
+
+static void gtk_text_view_accessible_class_init (GtkTextViewAccessibleClass *klass);
+static void gtk_text_view_accessible_init (GtkTextViewAccessible *text_view);
+
+static void gtk_text_view_accessible_real_initialize (AtkObject *obj,
+ gpointer data);
+static void gtk_text_view_accessible_real_notify_gtk (GObject *obj,
+ GParamSpec *pspec);
+
+static void gtk_text_view_accessible_finalize (GObject *object);
+
+static void atk_text_interface_init (AtkTextIface *iface);
+
+/* atkobject.h */
+
+static AtkStateSet* gtk_text_view_accessible_ref_state_set (AtkObject *accessible);
+
+/* atktext.h */
+
+static gchar* gtk_text_view_accessible_get_text_after_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset);
+static gchar* gtk_text_view_accessible_get_text_at_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset);
+static gchar* gtk_text_view_accessible_get_text_before_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset);
+static gchar* gtk_text_view_accessible_get_text (AtkText*text,
+ gint start_offset,
+ gint end_offset);
+static gunichar gtk_text_view_accessible_get_character_at_offset (AtkText *text,
+ gint offset);
+static gint gtk_text_view_accessible_get_character_count (AtkText *text);
+static gint gtk_text_view_accessible_get_caret_offset (AtkText *text);
+static gboolean gtk_text_view_accessible_set_caret_offset (AtkText *text,
+ gint offset);
+static gint gtk_text_view_accessible_get_offset_at_point (AtkText *text,
+ gint x,
+ gint y,
+ AtkCoordType coords);
+static gint gtk_text_view_accessible_get_n_selections (AtkText *text);
+static gchar* gtk_text_view_accessible_get_selection (AtkText *text,
+ gint selection_num,
+ gint *start_offset,
+ gint *end_offset);
+static gboolean gtk_text_view_accessible_add_selection (AtkText *text,
+ gint start_offset,
+ gint end_offset);
+static gboolean gtk_text_view_accessible_remove_selection (AtkText *text,
+ gint selection_num);
+static gboolean gtk_text_view_accessible_set_selection (AtkText *text,
+ gint selection_num,
+ gint start_offset,
+ gint end_offset);
+static void gtk_text_view_accessible_get_character_extents (AtkText *text,
+ gint offset,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coords);
+static AtkAttributeSet * gtk_text_view_accessible_get_run_attributes
+ (AtkText *text,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset);
+static AtkAttributeSet * gtk_text_view_accessible_get_default_attributes
+ (AtkText *text);
+/* atkeditabletext.h */
+
+static void atk_editable_text_interface_init (AtkEditableTextIface *iface);
+static gboolean gtk_text_view_accessible_set_run_attributes (AtkEditableText *text,
+ AtkAttributeSet *attrib_set,
+ gint start_offset,
+ gint end_offset);
+static void gtk_text_view_accessible_set_text_contents (AtkEditableText *text,
+ const gchar *string);
+static void gtk_text_view_accessible_insert_text (AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *position);
+static void gtk_text_view_accessible_copy_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos);
+static void gtk_text_view_accessible_cut_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos);
+static void gtk_text_view_accessible_delete_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos);
+static void gtk_text_view_accessible_paste_text (AtkEditableText *text,
+ gint position);
+static void gtk_text_view_accessible_paste_received (GtkClipboard *clipboard,
+ const gchar *text,
+ gpointer data);
+/* AtkStreamableContent */
+static void atk_streamable_content_interface_init (AtkStreamableContentIface *iface);
+static gint gail_streamable_content_get_n_mime_types (AtkStreamableContent *streamable);
+static const gchar* gail_streamable_content_get_mime_type (AtkStreamableContent *streamable,
+ gint i);
+static GIOChannel* gail_streamable_content_get_stream (AtkStreamableContent *streamable,
+ const gchar *mime_type);
+/* getURI requires atk-1.12.0 or later
+static void gail_streamable_content_get_uri (AtkStreamableContent *streamable);
+*/
+
+/* Callbacks */
+
+static void _gtk_text_view_accessible_insert_text_cb (GtkTextBuffer *buffer,
+ GtkTextIter *arg1,
+ gchar *arg2,
+ gint arg3,
+ gpointer user_data);
+static void _gtk_text_view_accessible_delete_range_cb (GtkTextBuffer *buffer,
+ GtkTextIter *arg1,
+ GtkTextIter *arg2,
+ gpointer user_data);
+static void _gtk_text_view_accessible_changed_cb (GtkTextBuffer *buffer,
+ gpointer user_data);
+static void _gtk_text_view_accessible_mark_set_cb (GtkTextBuffer *buffer,
+ GtkTextIter *arg1,
+ GtkTextMark *arg2,
+ gpointer user_data);
+static gchar* get_text_near_offset (AtkText *text,
+ GailOffsetType function,
+ AtkTextBoundary boundary_type,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset);
+static gint get_insert_offset (GtkTextBuffer *buffer);
+static gint get_selection_bound (GtkTextBuffer *buffer);
+static void emit_text_caret_moved (GtkTextViewAccessible *gtk_text_view_accessible,
+ gint insert_offset);
+static gint insert_idle_handler (gpointer data);
+
+typedef struct _GtkTextViewAccessiblePaste GtkTextViewAccessiblePaste;
+
+struct _GtkTextViewAccessiblePaste
+{
+ GtkTextBuffer* buffer;
+ gint position;
+};
+
+G_DEFINE_TYPE_WITH_CODE (GtkTextViewAccessible, gtk_text_view_accessible, GAIL_TYPE_CONTAINER,
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_EDITABLE_TEXT, atk_editable_text_interface_init)
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_TEXT, atk_text_interface_init)
+ G_IMPLEMENT_INTERFACE (ATK_TYPE_STREAMABLE_CONTENT, atk_streamable_content_interface_init))
+
+static void
+gtk_text_view_accessible_class_init (GtkTextViewAccessibleClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
+ GailWidgetClass *widget_class;
+
+ widget_class = (GailWidgetClass*)klass;
+
+ gobject_class->finalize = gtk_text_view_accessible_finalize;
+
+ class->ref_state_set = gtk_text_view_accessible_ref_state_set;
+ class->initialize = gtk_text_view_accessible_real_initialize;
+
+ widget_class->notify_gtk = gtk_text_view_accessible_real_notify_gtk;
+}
+
+static void
+gtk_text_view_accessible_init (GtkTextViewAccessible *text_view)
+{
+ text_view->textutil = NULL;
+ text_view->signal_name = NULL;
+ text_view->previous_insert_offset = -1;
+ text_view->previous_selection_bound = -1;
+ text_view->insert_notify_handler = 0;
+}
+
+static void
+setup_buffer (GtkTextView *view,
+ GtkTextViewAccessible *gail_view)
+{
+ GtkTextBuffer *buffer;
+
+ buffer = gtk_text_view_get_buffer (view);
+
+ if (gail_view->textutil)
+ g_object_unref (gail_view->textutil);
+
+ gail_view->textutil = gail_text_util_new ();
+ gail_text_util_buffer_setup (gail_view->textutil, buffer);
+
+ /* Set up signal callbacks */
+ g_signal_connect_data (buffer, "insert-text",
+ (GCallback) _gtk_text_view_accessible_insert_text_cb, view, NULL, 0);
+ g_signal_connect_data (buffer, "delete-range",
+ (GCallback) _gtk_text_view_accessible_delete_range_cb, view, NULL, 0);
+ g_signal_connect_data (buffer, "mark-set",
+ (GCallback) _gtk_text_view_accessible_mark_set_cb, view, NULL, 0);
+ g_signal_connect_data (buffer, "changed",
+ (GCallback) _gtk_text_view_accessible_changed_cb, view, NULL, 0);
+
+}
+
+static void
+gtk_text_view_accessible_real_initialize (AtkObject *obj,
+ gpointer data)
+{
+ GtkTextView *view;
+ GtkTextViewAccessible *gail_view;
+
+ ATK_OBJECT_CLASS (gtk_text_view_accessible_parent_class)->initialize (obj, data);
+
+ view = GTK_TEXT_VIEW (data);
+
+ gail_view = GTK_TEXT_VIEW_ACCESSIBLE (obj);
+ setup_buffer (view, gail_view);
+
+ obj->role = ATK_ROLE_TEXT;
+
+}
+
+static void
+gtk_text_view_accessible_finalize (GObject *object)
+{
+ GtkTextViewAccessible *text_view = GTK_TEXT_VIEW_ACCESSIBLE (object);
+
+ g_object_unref (text_view->textutil);
+ if (text_view->insert_notify_handler)
+ g_source_remove (text_view->insert_notify_handler);
+
+ G_OBJECT_CLASS (gtk_text_view_accessible_parent_class)->finalize (object);
+}
+
+static void
+gtk_text_view_accessible_real_notify_gtk (GObject *obj,
+ GParamSpec *pspec)
+{
+ if (!strcmp (pspec->name, "editable"))
+ {
+ AtkObject *atk_obj;
+ gboolean editable;
+
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (obj));
+ editable = gtk_text_view_get_editable (GTK_TEXT_VIEW (obj));
+ atk_object_notify_state_change (atk_obj, ATK_STATE_EDITABLE,
+ editable);
+ }
+ else if (!strcmp (pspec->name, "buffer"))
+ {
+ AtkObject *atk_obj;
+
+ atk_obj = gtk_widget_get_accessible (GTK_WIDGET (obj));
+ setup_buffer (GTK_TEXT_VIEW (obj), GTK_TEXT_VIEW_ACCESSIBLE (atk_obj));
+ }
+ else
+ GAIL_WIDGET_CLASS (gtk_text_view_accessible_parent_class)->notify_gtk (obj, pspec);
+}
+
+/* atkobject.h */
+
+static AtkStateSet*
+gtk_text_view_accessible_ref_state_set (AtkObject *accessible)
+{
+ AtkStateSet *state_set;
+ GtkTextView *text_view;
+ GtkWidget *widget;
+
+ state_set = ATK_OBJECT_CLASS (gtk_text_view_accessible_parent_class)->ref_state_set (accessible);
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+
+ if (widget == NULL)
+ return state_set;
+
+ text_view = GTK_TEXT_VIEW (widget);
+
+ if (gtk_text_view_get_editable (text_view))
+ atk_state_set_add_state (state_set, ATK_STATE_EDITABLE);
+ atk_state_set_add_state (state_set, ATK_STATE_MULTI_LINE);
+
+ return state_set;
+}
+
+/* atktext.h */
+
+static void
+atk_text_interface_init (AtkTextIface *iface)
+{
+ iface->get_text = gtk_text_view_accessible_get_text;
+ iface->get_text_after_offset = gtk_text_view_accessible_get_text_after_offset;
+ iface->get_text_at_offset = gtk_text_view_accessible_get_text_at_offset;
+ iface->get_text_before_offset = gtk_text_view_accessible_get_text_before_offset;
+ iface->get_character_at_offset = gtk_text_view_accessible_get_character_at_offset;
+ iface->get_character_count = gtk_text_view_accessible_get_character_count;
+ iface->get_caret_offset = gtk_text_view_accessible_get_caret_offset;
+ iface->set_caret_offset = gtk_text_view_accessible_set_caret_offset;
+ iface->get_offset_at_point = gtk_text_view_accessible_get_offset_at_point;
+ iface->get_character_extents = gtk_text_view_accessible_get_character_extents;
+ iface->get_n_selections = gtk_text_view_accessible_get_n_selections;
+ iface->get_selection = gtk_text_view_accessible_get_selection;
+ iface->add_selection = gtk_text_view_accessible_add_selection;
+ iface->remove_selection = gtk_text_view_accessible_remove_selection;
+ iface->set_selection = gtk_text_view_accessible_set_selection;
+ iface->get_run_attributes = gtk_text_view_accessible_get_run_attributes;
+ iface->get_default_attributes = gtk_text_view_accessible_get_default_attributes;
+}
+
+static gchar*
+gtk_text_view_accessible_get_text (AtkText *text,
+ gint start_offset,
+ gint end_offset)
+{
+ GtkTextView *view;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return NULL;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset);
+
+ return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+}
+
+static gchar*
+gtk_text_view_accessible_get_text_after_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return NULL;
+
+ return get_text_near_offset (text, GAIL_AFTER_OFFSET,
+ boundary_type, offset,
+ start_offset, end_offset);
+}
+
+static gchar*
+gtk_text_view_accessible_get_text_at_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return NULL;
+
+ return get_text_near_offset (text, GAIL_AT_OFFSET,
+ boundary_type, offset,
+ start_offset, end_offset);
+}
+
+static gchar*
+gtk_text_view_accessible_get_text_before_offset (AtkText *text,
+ gint offset,
+ AtkTextBoundary boundary_type,
+ gint *start_offset,
+ gint *end_offset)
+{
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return NULL;
+
+ return get_text_near_offset (text, GAIL_BEFORE_OFFSET,
+ boundary_type, offset,
+ start_offset, end_offset);
+}
+
+static gunichar
+gtk_text_view_accessible_get_character_at_offset (AtkText *text,
+ gint offset)
+{
+ GtkWidget *widget;
+ GtkTextIter start, end;
+ GtkTextBuffer *buffer;
+ gchar *string;
+ gunichar unichar;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ return '\0';
+
+ buffer = GTK_TEXT_VIEW_ACCESSIBLE (text)->textutil->buffer;
+ if (offset >= gtk_text_buffer_get_char_count (buffer))
+ return '\0';
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, offset);
+ end = start;
+ gtk_text_iter_forward_char (&end);
+ string = gtk_text_buffer_get_slice (buffer, &start, &end, FALSE);
+ unichar = g_utf8_get_char (string);
+ g_free(string);
+ return unichar;
+}
+
+static gint
+gtk_text_view_accessible_get_character_count (AtkText *text)
+{
+ GtkTextView *view;
+ GtkTextBuffer *buffer;
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return 0;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+ return gtk_text_buffer_get_char_count (buffer);
+}
+
+static gint
+gtk_text_view_accessible_get_caret_offset (AtkText *text)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return 0;
+
+ view = GTK_TEXT_VIEW (widget);
+ return get_insert_offset (gtk_text_view_get_buffer (view));
+}
+
+static gboolean
+gtk_text_view_accessible_set_caret_offset (AtkText *text,
+ gint offset)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter pos_itr;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return FALSE;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, offset);
+ gtk_text_buffer_place_cursor (buffer, &pos_itr);
+ gtk_text_view_scroll_to_iter (view, &pos_itr, 0, FALSE, 0, 0);
+ return TRUE;
+}
+
+static gint
+gtk_text_view_accessible_get_offset_at_point (AtkText *text,
+ gint x,
+ gint y,
+ AtkCoordType coords)
+{
+ GtkTextView *view;
+ GtkTextIter loc_itr;
+ gint x_widget, y_widget, x_window, y_window, buff_x, buff_y;
+ GtkWidget *widget;
+ GdkWindow *window;
+ GdkRectangle rect;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return -1;
+
+ view = GTK_TEXT_VIEW (widget);
+
+ window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_WIDGET);
+ gdk_window_get_origin (window, &x_widget, &y_widget);
+
+ if (coords == ATK_XY_SCREEN)
+ {
+ x = x - x_widget;
+ y = y - y_widget;
+ }
+ else if (coords == ATK_XY_WINDOW)
+ {
+ window = gdk_window_get_toplevel (window);
+ gdk_window_get_origin (window, &x_window, &y_window);
+
+ x = x - x_widget + x_window;
+ y = y - y_widget + y_window;
+ }
+ else
+ return -1;
+
+ gtk_text_view_window_to_buffer_coords (view, GTK_TEXT_WINDOW_WIDGET,
+ x, y, &buff_x, &buff_y);
+ gtk_text_view_get_visible_rect (view, &rect);
+ /*
+ * Clamp point to visible rectangle
+ */
+ buff_x = CLAMP (buff_x, rect.x, rect.x + rect.width - 1);
+ buff_y = CLAMP (buff_y, rect.y, rect.y + rect.height - 1);
+
+ gtk_text_view_get_iter_at_location (view, &loc_itr, buff_x, buff_y);
+ /*
+ * The iter at a location sometimes points to the next character.
+ * See bug 111031. We work around that
+ */
+ gtk_text_view_get_iter_location (view, &loc_itr, &rect);
+ if (buff_x < rect.x)
+ gtk_text_iter_backward_char (&loc_itr);
+ return gtk_text_iter_get_offset (&loc_itr);
+}
+
+static void
+gtk_text_view_accessible_get_character_extents (AtkText *text,
+ gint offset,
+ gint *x,
+ gint *y,
+ gint *width,
+ gint *height,
+ AtkCoordType coords)
+{
+ GtkTextView *view;
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ GtkWidget *widget;
+ GdkRectangle rectangle;
+ GdkWindow *window;
+ gint x_widget, y_widget, x_window, y_window;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+ gtk_text_buffer_get_iter_at_offset (buffer, &iter, offset);
+ gtk_text_view_get_iter_location (view, &iter, &rectangle);
+
+ window = gtk_text_view_get_window (view, GTK_TEXT_WINDOW_WIDGET);
+ gdk_window_get_origin (window, &x_widget, &y_widget);
+
+ *height = rectangle.height;
+ *width = rectangle.width;
+
+ gtk_text_view_buffer_to_window_coords (view, GTK_TEXT_WINDOW_WIDGET,
+ rectangle.x, rectangle.y, x, y);
+ if (coords == ATK_XY_WINDOW)
+ {
+ window = gdk_window_get_toplevel (window);
+ gdk_window_get_origin (window, &x_window, &y_window);
+ *x += x_widget - x_window;
+ *y += y_widget - y_window;
+ }
+ else if (coords == ATK_XY_SCREEN)
+ {
+ *x += x_widget;
+ *y += y_widget;
+ }
+ else
+ {
+ *x = 0;
+ *y = 0;
+ *height = 0;
+ *width = 0;
+ }
+}
+
+static AtkAttributeSet*
+gtk_text_view_accessible_get_run_attributes (AtkText *text,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset)
+{
+ GtkTextView *view;
+ GtkTextBuffer *buffer;
+ GtkWidget *widget;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return NULL;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ return gail_misc_buffer_get_run_attributes (buffer, offset,
+ start_offset, end_offset);
+}
+
+static AtkAttributeSet*
+add_text_attribute (AtkAttributeSet *attrib_set, AtkTextAttribute attr, gint i)
+{
+ const gchar *value;
+
+ value = atk_text_attribute_get_value (attr, i);
+
+ return gail_misc_add_attribute (attrib_set, i, g_strdup (value));
+}
+
+static AtkAttributeSet*
+gtk_text_view_accessible_get_default_attributes (AtkText *text)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextAttributes *text_attrs;
+ AtkAttributeSet *attrib_set = NULL;
+ PangoFontDescription *font;
+ gchar *value;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return NULL;
+
+ view = GTK_TEXT_VIEW (widget);
+ text_attrs = gtk_text_view_get_default_attributes (view);
+
+ font = text_attrs->font;
+
+ if (font)
+ {
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_STYLE,
+ pango_font_description_get_style (font));
+
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_VARIANT,
+ pango_font_description_get_variant (font));
+
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_STRETCH,
+ pango_font_description_get_stretch (font));
+
+ value = g_strdup (pango_font_description_get_family (font));
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_FAMILY_NAME, value);
+
+ value = g_strdup_printf ("%d", pango_font_description_get_weight (font));
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_WEIGHT, value);
+
+ value = g_strdup_printf ("%i", pango_font_description_get_size (font) / PANGO_SCALE);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_SIZE, value);
+ }
+
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_JUSTIFICATION, text_attrs->justification);
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_DIRECTION, text_attrs->direction);
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_WRAP_MODE, text_attrs->wrap_mode);
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_EDITABLE, text_attrs->editable);
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_INVISIBLE, text_attrs->invisible);
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_BG_FULL_HEIGHT, text_attrs->bg_full_height);
+
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_STRIKETHROUGH,
+ text_attrs->appearance.strikethrough);
+ attrib_set = add_text_attribute (attrib_set, ATK_TEXT_ATTR_UNDERLINE,
+ text_attrs->appearance.underline);
+
+ value = g_strdup_printf ("%u,%u,%u",
+ text_attrs->appearance.bg_color.red,
+ text_attrs->appearance.bg_color.green,
+ text_attrs->appearance.bg_color.blue);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_BG_COLOR, value);
+
+ value = g_strdup_printf ("%u,%u,%u",
+ text_attrs->appearance.fg_color.red,
+ text_attrs->appearance.fg_color.green,
+ text_attrs->appearance.fg_color.blue);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_FG_COLOR, value);
+
+ value = g_strdup_printf ("%g", text_attrs->font_scale);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_SCALE, value);
+
+ value = g_strdup ((gchar *)(text_attrs->language));
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_LANGUAGE, value);
+
+ value = g_strdup_printf ("%i", text_attrs->appearance.rise);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_RISE, value);
+
+ value = g_strdup_printf ("%i", text_attrs->pixels_inside_wrap);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP, value);
+
+ value = g_strdup_printf ("%i", text_attrs->pixels_below_lines);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_PIXELS_BELOW_LINES, value);
+
+ value = g_strdup_printf ("%i", text_attrs->pixels_above_lines);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_PIXELS_ABOVE_LINES, value);
+
+ value = g_strdup_printf ("%i", text_attrs->indent);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_INDENT, value);
+
+ value = g_strdup_printf ("%i", text_attrs->left_margin);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_LEFT_MARGIN, value);
+
+ value = g_strdup_printf ("%i", text_attrs->right_margin);
+ attrib_set = gail_misc_add_attribute (attrib_set, ATK_TEXT_ATTR_RIGHT_MARGIN, value);
+
+ gtk_text_attributes_unref (text_attrs);
+ return attrib_set;
+}
+
+static gint
+gtk_text_view_accessible_get_n_selections (AtkText *text)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gint select_start, select_end;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return -1;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+ select_start = gtk_text_iter_get_offset (&start);
+ select_end = gtk_text_iter_get_offset (&end);
+
+ if (select_start != select_end)
+ return 1;
+ else
+ return 0;
+}
+
+static gchar*
+gtk_text_view_accessible_get_selection (AtkText *text,
+ gint selection_num,
+ gint *start_pos,
+ gint *end_pos)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return NULL;
+
+ /* Only let the user get the selection if one is set, and if the
+ * selection_num is 0.
+ */
+ if (selection_num != 0)
+ return NULL;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+ *start_pos = gtk_text_iter_get_offset (&start);
+ *end_pos = gtk_text_iter_get_offset (&end);
+
+ if (*start_pos != *end_pos)
+ return gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ else
+ return NULL;
+}
+
+static gboolean
+gtk_text_view_accessible_add_selection (AtkText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter pos_itr;
+ GtkTextIter start, end;
+ gint select_start, select_end;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return FALSE;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_selection_bounds (buffer, &start, &end);
+ select_start = gtk_text_iter_get_offset (&start);
+ select_end = gtk_text_iter_get_offset (&end);
+
+ /* If there is already a selection, then don't allow another to be added,
+ * since GtkTextView only supports one selected region.
+ */
+ if (select_start == select_end)
+ {
+ gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, start_pos);
+ gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &pos_itr);
+ gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, end_pos);
+ gtk_text_buffer_move_mark_by_name (buffer, "insert", &pos_itr);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static gboolean
+gtk_text_view_accessible_remove_selection (AtkText *text,
+ gint selection_num)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextMark *cursor_mark;
+ GtkTextIter cursor_itr;
+ GtkTextIter start, end;
+ gint select_start, select_end;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return FALSE;
+
+ if (selection_num != 0)
+ return FALSE;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
+ select_start = gtk_text_iter_get_offset(&start);
+ select_end = gtk_text_iter_get_offset(&end);
+
+ if (select_start != select_end)
+ {
+ /* Setting the start & end of the selected region to the caret position
+ * turns off the selection.
+ */
+ cursor_mark = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &cursor_itr, cursor_mark);
+ gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &cursor_itr);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static gboolean
+gtk_text_view_accessible_set_selection (AtkText *text,
+ gint selection_num,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter pos_itr;
+ GtkTextIter start, end;
+ gint select_start, select_end;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ {
+ /* State is defunct */
+ return FALSE;
+ }
+
+ /* Only let the user move the selection if one is set, and if the
+ * selection_num is 0
+ */
+ if (selection_num != 0)
+ return FALSE;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_selection_bounds(buffer, &start, &end);
+ select_start = gtk_text_iter_get_offset(&start);
+ select_end = gtk_text_iter_get_offset(&end);
+
+ if (select_start != select_end)
+ {
+ gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, start_pos);
+ gtk_text_buffer_move_mark_by_name (buffer, "selection_bound", &pos_itr);
+ gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, end_pos);
+ gtk_text_buffer_move_mark_by_name (buffer, "insert", &pos_itr);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/* atkeditabletext.h */
+
+static void
+atk_editable_text_interface_init (AtkEditableTextIface *iface)
+{
+ iface->set_text_contents = gtk_text_view_accessible_set_text_contents;
+ iface->insert_text = gtk_text_view_accessible_insert_text;
+ iface->copy_text = gtk_text_view_accessible_copy_text;
+ iface->cut_text = gtk_text_view_accessible_cut_text;
+ iface->delete_text = gtk_text_view_accessible_delete_text;
+ iface->paste_text = gtk_text_view_accessible_paste_text;
+ iface->set_run_attributes = gtk_text_view_accessible_set_run_attributes;
+}
+
+static gboolean
+gtk_text_view_accessible_set_run_attributes (AtkEditableText *text,
+ AtkAttributeSet *attrib_set,
+ gint start_offset,
+ gint end_offset)
+{
+ GtkTextView *view;
+ GtkTextBuffer *buffer;
+ GtkWidget *widget;
+ GtkTextTag *tag;
+ GtkTextIter start;
+ GtkTextIter end;
+ gint j;
+ GdkColor *color;
+ gchar** RGB_vals;
+ GSList *l;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return FALSE;
+
+ view = GTK_TEXT_VIEW (widget);
+ if (!gtk_text_view_get_editable (view))
+ return FALSE;
+
+ buffer = gtk_text_view_get_buffer (view);
+
+ if (attrib_set == NULL)
+ return FALSE;
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, start_offset);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_offset);
+
+ tag = gtk_text_buffer_create_tag (buffer, NULL, NULL);
+
+ for (l = attrib_set; l; l = l->next)
+ {
+ gchar *name;
+ gchar *value;
+ AtkAttribute *at;
+
+ at = l->data;
+
+ name = at->name;
+ value = at->value;
+
+ if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_LEFT_MARGIN)))
+ g_object_set (G_OBJECT (tag), "left_margin", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_RIGHT_MARGIN)))
+ g_object_set (G_OBJECT (tag), "right_margin", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_INDENT)))
+ g_object_set (G_OBJECT (tag), "indent", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_PIXELS_ABOVE_LINES)))
+ g_object_set (G_OBJECT (tag), "pixels_above_lines", atoi (value), NULL);
+
+ else if (!strcmp(name, atk_text_attribute_get_name (ATK_TEXT_ATTR_PIXELS_BELOW_LINES)))
+ g_object_set (G_OBJECT (tag), "pixels_below_lines", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_PIXELS_INSIDE_WRAP)))
+ g_object_set (G_OBJECT (tag), "pixels_inside_wrap", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_SIZE)))
+ g_object_set (G_OBJECT (tag), "size", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_RISE)))
+ g_object_set (G_OBJECT (tag), "rise", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_WEIGHT)))
+ g_object_set (G_OBJECT (tag), "weight", atoi (value), NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_BG_FULL_HEIGHT)))
+ {
+ g_object_set (G_OBJECT (tag), "bg_full_height",
+ (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_BG_FULL_HEIGHT, 0))),
+ NULL);
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_LANGUAGE)))
+ g_object_set (G_OBJECT (tag), "language", value, NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_FAMILY_NAME)))
+ g_object_set (G_OBJECT (tag), "family", value, NULL);
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_EDITABLE)))
+ {
+ g_object_set (G_OBJECT (tag), "editable",
+ (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_EDITABLE, 0))),
+ NULL);
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_INVISIBLE)))
+ {
+ g_object_set (G_OBJECT (tag), "invisible",
+ (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_EDITABLE, 0))),
+ NULL);
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_UNDERLINE)))
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_UNDERLINE, j)))
+ {
+ g_object_set (G_OBJECT (tag), "underline", j, NULL);
+ break;
+ }
+ }
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_STRIKETHROUGH)))
+ {
+ g_object_set (G_OBJECT (tag), "strikethrough",
+ (strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_STRIKETHROUGH, 0))),
+ NULL);
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_BG_COLOR)))
+ {
+ RGB_vals = g_strsplit (value, ",", 3);
+ color = g_malloc (sizeof (GdkColor));
+ color->red = atoi (RGB_vals[0]);
+ color->green = atoi (RGB_vals[1]);
+ color->blue = atoi (RGB_vals[2]);
+ g_object_set (G_OBJECT (tag), "background_gdk", color, NULL);
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_FG_COLOR)))
+ {
+ RGB_vals = g_strsplit (value, ",", 3);
+ color = g_malloc (sizeof (GdkColor));
+ color->red = atoi (RGB_vals[0]);
+ color->green = atoi (RGB_vals[1]);
+ color->blue = atoi (RGB_vals[2]);
+ g_object_set (G_OBJECT (tag), "foreground_gdk", color, NULL);
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_STRETCH)))
+ {
+ for (j = 0; j < 9; j++)
+ {
+ if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_STRETCH, j)))
+ {
+ g_object_set (G_OBJECT (tag), "stretch", j, NULL);
+ break;
+ }
+ }
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_JUSTIFICATION)))
+ {
+ for (j = 0; j < 4; j++)
+ {
+ if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_JUSTIFICATION, j)))
+ {
+ g_object_set (G_OBJECT (tag), "justification", j, NULL);
+ break;
+ }
+ }
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_DIRECTION)))
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_DIRECTION, j)))
+ {
+ g_object_set (G_OBJECT (tag), "direction", j, NULL);
+ break;
+ }
+ }
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_VARIANT)))
+ {
+ for (j = 0; j < 2; j++)
+ {
+ if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_VARIANT, j)))
+ {
+ g_object_set (G_OBJECT (tag), "variant", j, NULL);
+ break;
+ }
+ }
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_WRAP_MODE)))
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_WRAP_MODE, j)))
+ {
+ g_object_set (G_OBJECT (tag), "wrap_mode", j, NULL);
+ break;
+ }
+ }
+ }
+
+ else if (!strcmp (name, atk_text_attribute_get_name (ATK_TEXT_ATTR_STYLE)))
+ {
+ for (j = 0; j < 3; j++)
+ {
+ if (!strcmp (value, atk_text_attribute_get_value (ATK_TEXT_ATTR_STYLE, j)))
+ {
+ g_object_set (G_OBJECT (tag), "style", j, NULL);
+ break;
+ }
+ }
+ }
+
+ else
+ return FALSE;
+ }
+
+ gtk_text_buffer_apply_tag (buffer, tag, &start, &end);
+
+ return TRUE;
+}
+
+static void
+gtk_text_view_accessible_set_text_contents (AtkEditableText *text,
+ const gchar *string)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return;
+
+ view = GTK_TEXT_VIEW (widget);
+ if (!gtk_text_view_get_editable (view))
+ return;
+ buffer = gtk_text_view_get_buffer (view);
+
+ /* The -1 indicates that the input string must be null-terminated */
+ gtk_text_buffer_set_text (buffer, string, -1);
+}
+
+static void
+gtk_text_view_accessible_insert_text (AtkEditableText *text,
+ const gchar *string,
+ gint length,
+ gint *position)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter pos_itr;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return;
+
+ view = GTK_TEXT_VIEW (widget);
+ if (!gtk_text_view_get_editable (view))
+ return;
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &pos_itr, *position);
+ gtk_text_buffer_insert (buffer, &pos_itr, string, length);
+}
+
+static void
+gtk_text_view_accessible_copy_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gchar *str;
+ GtkClipboard *clipboard;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return;
+
+ view = GTK_TEXT_VIEW (widget);
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, start_pos);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_pos);
+ str = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
+ GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, str, -1);
+}
+
+static void
+gtk_text_view_accessible_cut_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter start, end;
+ gchar *str;
+ GtkClipboard *clipboard;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return;
+
+ view = GTK_TEXT_VIEW (widget);
+ if (!gtk_text_view_get_editable (view))
+ return;
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, start_pos);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, end_pos);
+ str = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
+ GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_set_text (clipboard, str, -1);
+ gtk_text_buffer_delete (buffer, &start, &end);
+}
+
+static void
+gtk_text_view_accessible_delete_text (AtkEditableText *text,
+ gint start_pos,
+ gint end_pos)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextIter start_itr;
+ GtkTextIter end_itr;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return;
+
+ view = GTK_TEXT_VIEW (widget);
+ if (!gtk_text_view_get_editable (view))
+ return;
+ buffer = gtk_text_view_get_buffer (view);
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &start_itr, start_pos);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end_itr, end_pos);
+ gtk_text_buffer_delete (buffer, &start_itr, &end_itr);
+}
+
+static void
+gtk_text_view_accessible_paste_text (AtkEditableText *text,
+ gint position)
+{
+ GtkTextView *view;
+ GtkWidget *widget;
+ GtkTextBuffer *buffer;
+ GtkTextViewAccessiblePaste paste_struct;
+ GtkClipboard *clipboard;
+
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (text));
+ if (widget == NULL)
+ /* State is defunct */
+ return;
+
+ view = GTK_TEXT_VIEW (widget);
+ if (!gtk_text_view_get_editable (view))
+ return;
+ buffer = gtk_text_view_get_buffer (view);
+
+ paste_struct.buffer = buffer;
+ paste_struct.position = position;
+
+ g_object_ref (paste_struct.buffer);
+ clipboard = gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
+ GDK_SELECTION_CLIPBOARD);
+ gtk_clipboard_request_text (clipboard,
+ gtk_text_view_accessible_paste_received, &paste_struct);
+}
+
+static void
+gtk_text_view_accessible_paste_received (GtkClipboard *clipboard,
+ const gchar *text,
+ gpointer data)
+{
+ GtkTextViewAccessiblePaste* paste_struct = (GtkTextViewAccessiblePaste *)data;
+ GtkTextIter pos_itr;
+
+ if (text)
+ {
+ gtk_text_buffer_get_iter_at_offset (paste_struct->buffer, &pos_itr,
+ paste_struct->position);
+ gtk_text_buffer_insert (paste_struct->buffer, &pos_itr, text, -1);
+ }
+
+ g_object_unref (paste_struct->buffer);
+}
+
+/* Callbacks */
+
+/* Note arg1 returns the start of the insert range, arg3 returns the
+ * end of the insert range if multiple characters are inserted. If one
+ * character is inserted they have the same value, which is the caret
+ * location. arg2 returns the begin location of the insert.
+ */
+static void
+_gtk_text_view_accessible_insert_text_cb (GtkTextBuffer *buffer,
+ GtkTextIter *arg1,
+ gchar *arg2,
+ gint arg3,
+ gpointer user_data)
+{
+ GtkTextView *text = (GtkTextView *) user_data;
+ AtkObject *accessible;
+ GtkTextViewAccessible *gtk_text_view_accessible;
+ gint position;
+ gint length;
+
+ g_return_if_fail (arg3 > 0);
+
+ accessible = gtk_widget_get_accessible(GTK_WIDGET(text));
+ gtk_text_view_accessible = GTK_TEXT_VIEW_ACCESSIBLE (accessible);
+
+ gtk_text_view_accessible->signal_name = "text_changed::insert";
+ position = gtk_text_iter_get_offset (arg1);
+ length = g_utf8_strlen(arg2, arg3);
+
+ if (gtk_text_view_accessible->length == 0)
+ {
+ gtk_text_view_accessible->position = position;
+ gtk_text_view_accessible->length = length;
+ }
+ else if (gtk_text_view_accessible->position + gtk_text_view_accessible->length == position)
+ {
+ gtk_text_view_accessible->length += length;
+ }
+ else
+ {
+ /*
+ * We have a non-contiguous insert so report what we have
+ */
+ if (gtk_text_view_accessible->insert_notify_handler)
+ {
+ g_source_remove (gtk_text_view_accessible->insert_notify_handler);
+ }
+ gtk_text_view_accessible->insert_notify_handler = 0;
+ insert_idle_handler (gtk_text_view_accessible);
+ gtk_text_view_accessible->position = position;
+ gtk_text_view_accessible->length = length;
+ }
+
+ /*
+ * The signal will be emitted when the changed signal is received
+ */
+}
+
+/* Note arg1 returns the start of the delete range, arg2 returns the
+ * end of the delete range if multiple characters are deleted. If one
+ * character is deleted they have the same value, which is the caret
+ * location.
+ */
+static void
+_gtk_text_view_accessible_delete_range_cb (GtkTextBuffer *buffer,
+ GtkTextIter *arg1,
+ GtkTextIter *arg2,
+ gpointer user_data)
+{
+ GtkTextView *text = (GtkTextView *) user_data;
+ AtkObject *accessible;
+ GtkTextViewAccessible *gtk_text_view_accessible;
+ gint offset = gtk_text_iter_get_offset (arg1);
+ gint length = gtk_text_iter_get_offset (arg2) - offset;
+
+ accessible = gtk_widget_get_accessible(GTK_WIDGET(text));
+ gtk_text_view_accessible = GTK_TEXT_VIEW_ACCESSIBLE (accessible);
+ if (gtk_text_view_accessible->insert_notify_handler)
+ {
+ g_source_remove (gtk_text_view_accessible->insert_notify_handler);
+ gtk_text_view_accessible->insert_notify_handler = 0;
+ if (gtk_text_view_accessible->position == offset &&
+ gtk_text_view_accessible->length == length)
+ {
+ /*
+ * Do not bother with insert and delete notifications
+ */
+ gtk_text_view_accessible->signal_name = NULL;
+ gtk_text_view_accessible->position = 0;
+ gtk_text_view_accessible->length = 0;
+ return;
+ }
+
+ insert_idle_handler (gtk_text_view_accessible);
+ }
+ g_signal_emit_by_name (accessible, "text_changed::delete",
+ offset, length);
+}
+
+/* Note arg1 and arg2 point to the same offset, which is the caret
+ * position after the move
+ */
+static void
+_gtk_text_view_accessible_mark_set_cb (GtkTextBuffer *buffer,
+ GtkTextIter *arg1,
+ GtkTextMark *arg2,
+ gpointer user_data)
+{
+ GtkTextView *text = (GtkTextView *) user_data;
+ AtkObject *accessible;
+ GtkTextViewAccessible *gtk_text_view_accessible;
+ const char *mark_name = gtk_text_mark_get_name(arg2);
+
+ accessible = gtk_widget_get_accessible(GTK_WIDGET(text));
+ gtk_text_view_accessible = GTK_TEXT_VIEW_ACCESSIBLE (accessible);
+
+ /*
+ * Only generate the signal for the "insert" mark, which
+ * represents the cursor.
+ */
+ if (mark_name && !strcmp(mark_name, "insert"))
+ {
+ int insert_offset, selection_bound;
+ gboolean selection_changed;
+
+ insert_offset = gtk_text_iter_get_offset (arg1);
+
+ selection_bound = get_selection_bound (buffer);
+ if (selection_bound != insert_offset)
+ {
+ if (selection_bound != gtk_text_view_accessible->previous_selection_bound ||
+ insert_offset != gtk_text_view_accessible->previous_insert_offset)
+ {
+ selection_changed = TRUE;
+ }
+ else
+ {
+ selection_changed = FALSE;
+ }
+ }
+ else if (gtk_text_view_accessible->previous_selection_bound != gtk_text_view_accessible->previous_insert_offset)
+ {
+ selection_changed = TRUE;
+ }
+ else
+ {
+ selection_changed = FALSE;
+ }
+
+ emit_text_caret_moved (gtk_text_view_accessible, insert_offset);
+ /*
+ * insert and selection_bound marks are different to a selection
+ * has changed
+ */
+ if (selection_changed)
+ g_signal_emit_by_name (accessible, "text_selection_changed");
+ gtk_text_view_accessible->previous_selection_bound = selection_bound;
+ }
+}
+
+static void
+_gtk_text_view_accessible_changed_cb (GtkTextBuffer *buffer,
+ gpointer user_data)
+{
+ GtkTextView *text = (GtkTextView *) user_data;
+ AtkObject *accessible;
+ GtkTextViewAccessible *gtk_text_view_accessible;
+
+ accessible = gtk_widget_get_accessible (GTK_WIDGET (text));
+ gtk_text_view_accessible = GTK_TEXT_VIEW_ACCESSIBLE (accessible);
+ if (gtk_text_view_accessible->signal_name)
+ {
+ if (!gtk_text_view_accessible->insert_notify_handler)
+ {
+ gtk_text_view_accessible->insert_notify_handler = gdk_threads_add_idle (insert_idle_handler, accessible);
+ }
+ return;
+ }
+ emit_text_caret_moved (gtk_text_view_accessible, get_insert_offset (buffer));
+ gtk_text_view_accessible->previous_selection_bound = get_selection_bound (buffer);
+}
+
+static gchar*
+get_text_near_offset (AtkText *text,
+ GailOffsetType function,
+ AtkTextBoundary boundary_type,
+ gint offset,
+ gint *start_offset,
+ gint *end_offset)
+{
+ GtkTextView *view;
+ gpointer layout = NULL;
+
+ view = GTK_TEXT_VIEW (gtk_accessible_get_widget (GTK_ACCESSIBLE (text)));
+
+ /*
+ * Pass the GtkTextView to the function gail_text_util_get_text()
+ * so it can find the start and end of the current line on the display.
+ */
+ if (boundary_type == ATK_TEXT_BOUNDARY_LINE_START ||
+ boundary_type == ATK_TEXT_BOUNDARY_LINE_END)
+ layout = view;
+
+ return gail_text_util_get_text (GTK_TEXT_VIEW_ACCESSIBLE (text)->textutil, layout,
+ function, boundary_type, offset,
+ start_offset, end_offset);
+}
+
+static gint
+get_insert_offset (GtkTextBuffer *buffer)
+{
+ GtkTextMark *cursor_mark;
+ GtkTextIter cursor_itr;
+
+ cursor_mark = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &cursor_itr, cursor_mark);
+ return gtk_text_iter_get_offset (&cursor_itr);
+}
+
+static gint
+get_selection_bound (GtkTextBuffer *buffer)
+{
+ GtkTextMark *selection_mark;
+ GtkTextIter selection_itr;
+
+ selection_mark = gtk_text_buffer_get_selection_bound (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &selection_itr, selection_mark);
+ return gtk_text_iter_get_offset (&selection_itr);
+}
+
+static void
+emit_text_caret_moved (GtkTextViewAccessible *gtk_text_view_accessible,
+ gint insert_offset)
+{
+ /*
+ * If we have text which has been inserted notify the user
+ */
+ if (gtk_text_view_accessible->insert_notify_handler)
+ {
+ g_source_remove (gtk_text_view_accessible->insert_notify_handler);
+ gtk_text_view_accessible->insert_notify_handler = 0;
+ insert_idle_handler (gtk_text_view_accessible);
+ }
+
+ if (insert_offset != gtk_text_view_accessible->previous_insert_offset)
+ {
+ /*
+ * If the caret position has not changed then don't bother notifying
+ *
+ * When mouse click is used to change caret position, notification
+ * is received on button down and button up.
+ */
+ g_signal_emit_by_name (gtk_text_view_accessible, "text_caret_moved", insert_offset);
+ gtk_text_view_accessible->previous_insert_offset = insert_offset;
+ }
+}
+
+static gint
+insert_idle_handler (gpointer data)
+{
+ GtkTextViewAccessible *gtk_text_view_accessible;
+ GtkTextBuffer *buffer;
+
+ gtk_text_view_accessible = GTK_TEXT_VIEW_ACCESSIBLE (data);
+
+ g_signal_emit_by_name (data,
+ gtk_text_view_accessible->signal_name,
+ gtk_text_view_accessible->position,
+ gtk_text_view_accessible->length);
+ gtk_text_view_accessible->signal_name = NULL;
+ gtk_text_view_accessible->position = 0;
+ gtk_text_view_accessible->length = 0;
+
+ buffer = gtk_text_view_accessible->textutil->buffer;
+ if (gtk_text_view_accessible->insert_notify_handler)
+ {
+ /*
+ * If called from idle handler notify caret moved
+ */
+ gtk_text_view_accessible->insert_notify_handler = 0;
+ emit_text_caret_moved (gtk_text_view_accessible, get_insert_offset (buffer));
+ gtk_text_view_accessible->previous_selection_bound = get_selection_bound (buffer);
+ }
+
+ return FALSE;
+}
+
+static void
+atk_streamable_content_interface_init (AtkStreamableContentIface *iface)
+{
+ iface->get_n_mime_types = gail_streamable_content_get_n_mime_types;
+ iface->get_mime_type = gail_streamable_content_get_mime_type;
+ iface->get_stream = gail_streamable_content_get_stream;
+}
+
+static gint gail_streamable_content_get_n_mime_types (AtkStreamableContent *streamable)
+{
+ gint n_mime_types = 0;
+
+ if (GTK_TEXT_VIEW_ACCESSIBLE (streamable)->textutil)
+ {
+ int i;
+ gboolean advertises_plaintext = FALSE;
+ GdkAtom *atoms =
+ gtk_text_buffer_get_serialize_formats (
+ GTK_TEXT_VIEW_ACCESSIBLE (streamable)->textutil->buffer,
+ &n_mime_types);
+ for (i = 0; i < n_mime_types-1; ++i)
+ if (!strcmp ("text/plain", gdk_atom_name (atoms[i])))
+ advertises_plaintext = TRUE;
+ if (!advertises_plaintext) ++n_mime_types;
+ /* we support text/plain even if the GtkTextBuffer doesn't */
+ }
+ return n_mime_types;
+}
+
+static const gchar*
+gail_streamable_content_get_mime_type (AtkStreamableContent *streamable, gint i)
+{
+ if (GTK_TEXT_VIEW_ACCESSIBLE (streamable)->textutil)
+ {
+ gint n_mime_types = 0;
+ GdkAtom *atoms;
+ atoms = gtk_text_buffer_get_serialize_formats (
+ GTK_TEXT_VIEW_ACCESSIBLE (streamable)->textutil->buffer,
+ &n_mime_types);
+ if (i < n_mime_types)
+ {
+ return gdk_atom_name (atoms [i]);
+ }
+ else if (i == n_mime_types)
+ return "text/plain";
+ }
+ return NULL;
+}
+
+static GIOChannel* gail_streamable_content_get_stream (AtkStreamableContent *streamable,
+ const gchar *mime_type)
+{
+ gint i, n_mime_types = 0;
+ GdkAtom *atoms;
+ if (!GTK_TEXT_VIEW_ACCESSIBLE (streamable)->textutil)
+ return NULL;
+ atoms = gtk_text_buffer_get_serialize_formats (
+ GTK_TEXT_VIEW_ACCESSIBLE (streamable)->textutil->buffer,
+ &n_mime_types);
+ for (i = 0; i < n_mime_types; ++i)
+ {
+ if (!strcmp ("text/plain", mime_type) ||
+ !strcmp (gdk_atom_name (atoms[i]), mime_type)) {
+ GtkTextBuffer *buffer;
+ guint8 *cbuf;
+ GError *err = NULL;
+ gsize len, written;
+ gchar tname[80];
+ GtkTextIter start, end;
+ GIOChannel *gio = NULL;
+ int fd;
+ buffer = GTK_TEXT_VIEW_ACCESSIBLE (streamable)->textutil->buffer;
+ gtk_text_buffer_get_iter_at_offset (buffer, &start, 0);
+ gtk_text_buffer_get_iter_at_offset (buffer, &end, -1);
+ if (!strcmp ("text/plain", mime_type))
+ {
+ cbuf = (guint8*) gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ len = strlen ((const char *) cbuf);
+ }
+ else
+ {
+ cbuf = gtk_text_buffer_serialize (buffer, buffer, atoms[i], &start, &end, &len);
+ }
+ g_snprintf (tname, 20, "streamXXXXXX");
+ fd = g_mkstemp (tname);
+ gio = g_io_channel_unix_new (fd);
+ g_io_channel_set_encoding (gio, NULL, &err);
+ if (!err) g_io_channel_write_chars (gio, (const char *) cbuf, (gssize) len, &written, &err);
+ else g_message ("%s", err->message);
+ if (!err) g_io_channel_seek_position (gio, 0, G_SEEK_SET, &err);
+ else g_message ("%s", err->message);
+ if (!err) g_io_channel_flush (gio, &err);
+ else g_message ("%s", err->message);
+ if (err) {
+ g_message ("<error writing to stream [%s]>", tname);
+ g_error_free (err);
+ }
+ /* make sure the file is removed on unref of the giochannel */
+ else {
+ g_unlink (tname);
+ return gio;
+ }
+ }
+ }
+ return NULL;
+}
+
--- /dev/null
+/* GAIL - The GNOME Accessibility Implementation Library
+ * Copyright 2001 Sun Microsystems Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GTK_TEXT_VIEW_ACCESSIBLE_H__
+#define __GTK_TEXT_VIEW_ACCESSIBLE_H__
+
+#include "gailcontainer.h"
+#include "gailtextutil.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_TEXT_VIEW_ACCESSIBLE (gtk_text_view_accessible_get_type ())
+#define GTK_TEXT_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_TEXT_VIEW_ACCESSIBLE, GtkTextViewAccessible))
+#define GTK_TEXT_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_TEXT_VIEW_ACCESSIBLE, GtkTextViewAccessibleClass))
+#define GTK_IS_TEXT_VIEW_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_TEXT_VIEW_ACCESSIBLE))
+#define GTK_IS_TEXT_VIEW_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_TEXT_VIEW_ACCESSIBLE))
+#define GTK_TEXT_VIEW_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_TEXT_VIEW_ACCESSIBLE, GtkTextViewAccessibleClass))
+
+typedef struct _GtkTextViewAccessible GtkTextViewAccessible;
+typedef struct _GtkTextViewAccessibleClass GtkTextViewAccessibleClass;
+
+struct _GtkTextViewAccessible
+{
+ GailContainer parent;
+
+ GailTextUtil *textutil;
+ gint previous_insert_offset;
+ gint previous_selection_bound;
+ /*
+ * These fields store information about text changed
+ */
+ gchar *signal_name;
+ gint position;
+ gint length;
+
+ guint insert_notify_handler;
+};
+
+struct _GtkTextViewAccessibleClass
+{
+ GailContainerClass parent_class;
+};
+
+GType gtk_text_view_accessible_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GTK_TEXT_VIEW_ACCESSIBLE_H__ */
#include "gtkscrollable.h"
#include "gtktypebuiltins.h"
+#include "a11y/gtktextviewaccessible.h"
/**
* SECTION:gtktextview
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
g_type_class_add_private (gobject_class, sizeof (GtkTextViewPrivate));
+
+ gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_TEXT_VIEW_ACCESSIBLE);
}
static void